package com.coolwar.common;

import brave.internal.HexCodec;
import javax.servlet.http.HttpServletRequest;
import java.net.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.ZoneId;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;


public class CommonUtils {

    public final static ZoneId ZONDID = ZoneId.of( "GMT+08:00" );
    public final static Charset CHARSET = StandardCharsets.UTF_8;
    public final static String SLASH = "/";
    public final static String UNDERLINE = "_";
    public final static String HYPHEN = "-";
    public final static String COLON = ":";
    public final static String DEFAULTVERSION = "defaultVersion";
    public final static String HTTP_PROTOCOL_PREFIX = "http://";
    // 默认的提供服务的http端口
    public final static String defaultHttpPort = "9090";
    // 默认的提供服务的netty端口
    public final static String defaultAvroPort = "46111";
    // 监控用端口
    public final static String nanoHttpPort = "9091";

    // http请求方式
    public enum RequestMethod {
        GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE
    }

    public static String byteArrayToHex(byte[] byteArray) {

        // 首先初始化一个字符数组，用来存放每个16进制字符
        char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' };

        // new一个字符数组，这个就是用来组成结果字符串的（解释一下：一个byte是八位二进制，也就是2位十六进制字符（2的8次方等于16的2次方））
        char[] resultCharArray =new char[byteArray.length * 2];

        // 遍历字节数组，通过位运算（位运算效率高），转换成字符放到字符数组中去
        int index = 0;
        for (byte b : byteArray) {
            resultCharArray[index++] = hexDigits[b>>> 4 & 0xf];
            resultCharArray[index++] = hexDigits[b& 0xf];
        }
        // 字符数组组合成字符串返回
        return new String(resultCharArray);
    }

    public static String generalMD5(String input){
        try {
            // 拿到一个MD5转换器（如果想要SHA1参数换成”SHA1”）
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");

            // 输入的字符串转换成字节数组
            byte[] inputByteArray = input.getBytes();

            // inputByteArray是输入字符串转换得到的字节数组
            messageDigest.update(inputByteArray);

            // 转换并返回结果，也是字节数组，包含16个元素
            byte[] resultByteArray = messageDigest.digest();

            // 字符数组转换成字符串返回
            return byteArrayToHex(resultByteArray);
        } catch (NoSuchAlgorithmException e) {
            //异常就原样返回
            return input;
        }
    }

    /**
     * @param e
     *            异常类
     * @return 拼接打印 exception 栈内容
     */
    public static String stacktrace(Throwable e) {
        StringBuilder stack_trace = new StringBuilder();
        while (e != null) {
            String error_message = e.getMessage();
            error_message = error_message == null ? "\r\n" : error_message.concat("\r\n");
            stack_trace.append(error_message);
            stack_trace.append("<br>");
            for (StackTraceElement string : e.getStackTrace()) {
                stack_trace.append(string.toString());
                stack_trace.append("<br>");
            }
            e = e.getCause();
        }
        return stack_trace.toString();
    }

    //生成加盐的MD5
    public static String generalNonce(String s,String salt){

        return CommonUtils.generalMD5(CommonUtils.generalMD5(s.concat(salt)));
    }

    //根据网卡名字获取本地ip
    public static String getLocalIP(String... nic_names) {
        String ip = null;
        try {
            if (System.getProperty("os.name").indexOf("Linux") != -1) {
                for (String nic_name : nic_names) {
                    if (nic_name == null) {
                        continue;
                    }
                    ip = get_local_ip_bystartswith(nic_name);
                    if (ip != null) {
                        break;
                    }
                }
            } else {
                ip = InetAddress.getLocalHost().getHostAddress().toString();
            }
        } catch (SocketException | UnknownHostException e) {
            e.printStackTrace();
        }
        return ip;
    }

    private static String get_local_ip_bystartswith(String startsWith) throws SocketException {
        String ip = null;
        Enumeration<?> e1 = (Enumeration<?>) NetworkInterface.getNetworkInterfaces();
        while (e1.hasMoreElements()) {
            NetworkInterface ni = (NetworkInterface) e1.nextElement();
            if (ni.getName().startsWith(startsWith)) {
                Enumeration<?> e2 = ni.getInetAddresses();
                while (e2.hasMoreElements()) {
                    InetAddress ia = (InetAddress) e2.nextElement();
                    if (ia instanceof Inet6Address) {
                        continue;
                    }
                    ip = ia.getHostAddress();
                }
                break;
            }
        }
        return ip;
    }

    //获取第一个不是unknown的ip
    private static String getRealIp(String ip){
        if (ip.length() > 15) {
            String[] ips = ip.split(",");
            for (int index = 0; index < ips.length; index++) {
                String strIp = (String) ips[index];
                if (!("unknown".equalsIgnoreCase(strIp))) {
                    ip = strIp;
                    break;
                }
            }
            return ip;
        }else {
            return ip;
        }

    }

    //获取
    public final static String getRemoteIpAddress(HttpServletRequest request) {
        // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址
        String ip = "";

        try{
            ip = request.getHeader("X-Forwarded-For");
        }catch(Exception e){
            //e.printStackTrace();
            ip = "";
        }
        if (ip!=null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
            return getRealIp(ip);
        }

        try{
            ip = request.getHeader("Proxy-Client-IP");
        }catch(Exception e){
            //e.printStackTrace();
            ip = "";
        }

        if (ip!=null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
            return getRealIp(ip);
        }

        try{
            ip = request.getHeader("WL-Proxy-Client-IP");
        }catch(Exception e){
            //e.printStackTrace();
            ip = "";
        }

        if (ip!=null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
            return getRealIp(ip);
        }

        try{
            ip = request.getHeader("HTTP_CLIENT_IP");
        }catch(Exception e){
            //e.printStackTrace();
            ip = "";
        }

        if (ip!=null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
            return getRealIp(ip);
        }

        try{
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }catch(Exception e){
            //e.printStackTrace();
            ip = "";
        }

        if (ip!=null && ip.length() > 0 && !"unknown".equalsIgnoreCase(ip)) {
            return getRealIp(ip);
        }
        try{
            ip = request.getRemoteAddr();
        }catch(Exception e){
            //e.printStackTrace();
            ip = "";
        }
        return ip;

    }

    public static StackTraceElement[] getStack() {
        return Thread.currentThread().getStackTrace();


    }
    //在堆栈中找到调用方
    //日志类名称
    public static StackTraceElement findStack(String entryClassName) {
        // 获取堆栈信息
        StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
        if(null == callStack) {
            return null;
        }

        // 最原始被调用的堆栈信息
        StackTraceElement stack = null;

        // 循环遍历到日志类标识
        boolean isEachLogClass = false;

        // 遍历堆栈信息，获取出最原始被调用的方法信息
        for (StackTraceElement s : callStack) {
            // 遍历到日志类
            if(entryClassName.equals(s.getClassName())) {
                isEachLogClass = true;
            }
            // 下一个非日志类的堆栈，就是最原始被调用的方法
            if(isEachLogClass) {
                if(!entryClassName.equals(s.getClassName())) {
                    isEachLogClass = false;
                    stack = s;
                    break;
                }
            }
        }

        return stack;
    }



    public static String cutoffString(String src,int leftSize){
        if(src.length()<leftSize){
            return src;
        }
        return src.substring(0,leftSize/2).concat("...").concat(src.substring(src.length() - leftSize/2, src.length()));
    }

    public static void main(String[] args) {

        String nouce = CommonUtils.generalNonce("6c2575ada609490db512af09da36712e./v1/BusinessFollowHead/selectById.1553754260858", "6c2575ada609490db512af09da36712e");
        System.out.println(nouce);
    }

}
